package com.dctp.common.utils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 集合工具类（支持泛型、链式操作、空安全）
 */
public final class CollectUtil {

    // ---------------------- 基础工具 ----------------------

    /**
     * 判断集合是否为空
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断集合非空
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    // ---------------------- 集合转换 ----------------------

    /**
     * 集合元素类型转换（示例：List<String> → List<Integer>）
     * @param source 源集合
     * @param mapper 转换函数（如 Integer::parseInt）
     */
    public static <T, R> List<R> convert(Collection<T> source, Function<T, R> mapper) {
        return safeStream(source)
                .map(mapper)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 转换为Set（自动去重）
     */
    public static <T> Set<T> toSet(Collection<T> source) {
        return safeStream(source)
                .collect(Collectors.toSet());
    }

    // ---------------------- 过滤操作 ----------------------

    /**
     * 条件过滤
     * @param predicate 过滤条件（如 user -> user.getAge() > 18）
     */
    public static <T> List<T> filter(Collection<T> source, Predicate<T> predicate) {
        return safeStream(source)
                .filter(predicate)
                .collect(Collectors.toList());
    }

    // ---------------------- 分组与分区 ----------------------

    /**
     * 按属性分组（示例：按用户年龄分组）
     * @param classifier 分组依据（如 User::getAge）
     */
    public static <T, K> Map<K, List<T>> groupBy(Collection<T> source, Function<T, K> classifier) {
        return safeStream(source)
                .collect(Collectors.groupingBy(classifier));
    }

    /**
     * 分页（内存分页）
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页数量
     */
    public static <T> List<T> page(Collection<T> source, int pageNum, int pageSize) {
        if (isEmpty(source) || pageNum < 1 || pageSize < 1) {
            return Collections.emptyList();
        }
        
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, source.size());
        return new ArrayList<>(source).subList(start, end);
    }

    // ---------------------- 高级操作 ----------------------

    /**
     * 去重（基于某属性）
     * @param keyExtractor 去重依据（如 User::getId）
     */
    public static <T, K> List<T> distinctByKey(Collection<T> source, Function<T, K> keyExtractor) {
        return safeStream(source)
                .filter(distinctByKey(keyExtractor))
                .collect(Collectors.toList());
    }

    /**
     * 合并多个集合并去重
     */
    @SafeVarargs
    public static <T> List<T> merge(Collection<T>... collections) {
        return Arrays.stream(collections)
                .filter(CollectUtil::isNotEmpty)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
    }

    // ---------------------- 空安全处理 ----------------------

    /**
     * 创建空安全的Stream（自动处理null集合）
     */
    private static <T> Stream<T> safeStream(Collection<T> source) {
        return Optional.ofNullable(source)
                .map(Collection::stream)
                .orElseGet(Stream::empty);
    }

    /**
     * 去重辅助方法（基于属性）
     */
    private static <T, K> Predicate<T> distinctByKey(Function<T, K> keyExtractor) {
        Set<K> seen = new HashSet<>();
        return t -> seen.add(keyExtractor.apply(t));
    }

    // ---------------------- 其他实用方法 ----------------------

    /**
     * 获取第一个元素（空安全）
     */
    public static <T> Optional<T> first(Collection<T> source) {
        return safeStream(source).findFirst();
    }

    /**
     * 获取最后一个元素（空安全）
     */
    public static <T> Optional<T> last(Collection<T> source) {
        return safeStream(source)
                .reduce((first, second) -> second);
    }

    /**
     * 集合转字符串（自定义分隔符）
     */
    public static String join(Collection<?> source, String delimiter) {
        return safeStream(source)
                .map(Object::toString)
                .collect(Collectors.joining(delimiter));
    }

}